package cc.picc.mkt.service;

import java.util.Collections;
import java.util.Objects;

import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import cc.picc.commons.InconsistentInformationException;
import cc.picc.mkt.entity.BranchCampaignEntity;
import cc.picc.mkt.entity.CustomerEntity;
import cc.picc.mkt.entity.VehicleEntity;
import cc.picc.mkt.entity.VehiclePolicyEntity;
import cc.picc.mkt.entity.VehicleRenewCampaignObjectEntity;
import cc.picc.mkt.repository.BranchCampaignRepository;
import cc.picc.mkt.repository.CustomerRepository;
import cc.picc.mkt.repository.VehiclePolicyEntityRepository;
import cc.picc.mkt.repository.VehicleRenewCampaignObjectRepository;
import cc.picc.mkt.repository.VehicleRepository;

/**
 * 
 * @author lijinting01
 *
 */
@Service
@PropertySource(value = { "classpath:/processes.properties",
		"classpath:/cc/picc/mkt/service/message.properties" }, encoding = "UTF-8")
public class VehicleRenewCampaignServiceImpl implements VehicleRenewCampaignService {

	@Value("${vehicle.renew.insurance.process}")
	private String processDefinitionKey;

	@Value("${empty.policy.or.customer}")
	private String emptyPolicyOrCustomerMessage;

	@Value("${empty.vehicle}")
	private String emptyVehicleMessage;

	@Value("${inconsistent.policy.and.customer}")
	private String inconsistentPolicyAndCustomerMessage;

	@Value("${empty.campaign}")
	private String emptyCampaignMessage;

	private static final String VAR_NAME_CAMPAIGNOBJECT = "campaignObject";

	private CustomerRepository customerRepo;

	private VehiclePolicyEntityRepository policyRepo;

	private VehicleRepository vehicleRepo;

	private VehicleRenewCampaignObjectRepository vehicleRenewCampaignObjectRepo;

	private BranchCampaignRepository branchCampaignRepo;

	private RuntimeService runtimeService;

	/**
	 * 
	 * @param customerRepo
	 * @param policyRepo
	 * @param vehicleRepo
	 * @param vehicleRenewCampaignObjectRepo
	 * @param branchCampaignRepo
	 * @param runtimeService
	 */
	@Autowired
	public VehicleRenewCampaignServiceImpl(CustomerRepository customerRepo, VehiclePolicyEntityRepository policyRepo,
			VehicleRepository vehicleRepo, VehicleRenewCampaignObjectRepository vehicleRenewCampaignObjectRepo,
			BranchCampaignRepository branchCampaignRepo, RuntimeService runtimeService) {
		this.customerRepo = customerRepo;
		this.policyRepo = policyRepo;
		this.vehicleRepo = vehicleRepo;
		this.vehicleRenewCampaignObjectRepo = vehicleRenewCampaignObjectRepo;
		this.branchCampaignRepo = branchCampaignRepo;
		this.runtimeService = runtimeService;
	}

	@Override
	public String joinCampaign(Long campaignId, Long customerId, Long policyId) {

		BranchCampaignEntity campaign = findCampaign(campaignId);

		CustomerEntity customer = customerRepo.findOne(customerId);
		VehiclePolicyEntity policy = policyRepo.findOne(policyId);

		if (policy == null || customer == null)
			throw new EmptyResultDataAccessException(emptyPolicyOrCustomerMessage, 1);

		VehicleEntity vehicle = vehicleRepo.findOne(policy.getVehicle().getId());
		if (vehicle == null)
			throw new EmptyResultDataAccessException(emptyVehicleMessage, 1);

		if (!Objects.equals(customerId, policy.getCustomer().getId()))
			throw new InconsistentInformationException(inconsistentPolicyAndCustomerMessage);

		VehicleRenewCampaignObjectEntity rco = newVehicleRenewCampaignObjectEntity(campaign, customer, policy, vehicle);
		rco = vehicleRenewCampaignObjectRepo.save(rco);

		ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefinitionKey,
				Collections.singletonMap(VAR_NAME_CAMPAIGNOBJECT, rco));

		return pi.getId();
	}

	@Override
	public Page<VehicleRenewCampaignObjectEntity> findVehicleRenewCampaignObjectsByCampaign(String campaignName,
			int page, int size) {
		return vehicleRenewCampaignObjectRepo.findByCampaignName(campaignName, new PageRequest(page, size));
	}

	@Override
	public String joinCampaign(Long campaignId, Long customerId, String policyNo) {
		Page<VehiclePolicyEntity> page = policyRepo.findByPolicyNo(policyNo, new PageRequest(0, 1));
		if (page.getTotalElements() < 1)
			throw new EmptyResultDataAccessException(emptyPolicyOrCustomerMessage, 1);
		VehiclePolicyEntity e = page.getContent().get(0);// only取第一个
		return joinCampaign(campaignId, customerId, e.getId());
	}

	private BranchCampaignEntity findCampaign(Long id) {
		BranchCampaignEntity e = branchCampaignRepo.findOne(id);
		if (null == e)
			throw new EmptyResultDataAccessException(String.format(emptyCampaignMessage, id), 1);
		return e;
	}

	/**
	 * @param campaign
	 * @param customer
	 * @param policy
	 * @param vehicle
	 * @return
	 */
	private VehicleRenewCampaignObjectEntity newVehicleRenewCampaignObjectEntity(BranchCampaignEntity campaign,
			CustomerEntity customer, VehiclePolicyEntity policy, VehicleEntity vehicle) {
		VehicleRenewCampaignObjectEntity rco = new VehicleRenewCampaignObjectEntity();

		// 填充活动信息
		rco.setCampaign(campaign);

		// 填充客戶信息
		rco.setCustomer(customer);

		// 填充保单信息
		rco.setVehiclePolicy(policy);

		// 填充车辆信息
		rco.setVehicle(vehicle);
		return rco;
	}
}
